Guide complet sur la fusion et la jointure de DataFrames avec Python Pandas. Couvre les stratégies (internes, externes, gauches, droites) et des exemples pratiques pour l'analyse globale.
Fusion Python Pandas : Maîtriser les stratégies de jointure de DataFrame pour l'analyse de données
La manipulation des données est un aspect crucial de l'analyse de données, et la bibliothèque Pandas en Python fournit des outils puissants à cette fin. Parmi ces outils, la fusion et la jointure de DataFrames sont des opérations essentielles pour combiner des ensembles de données basées sur des colonnes ou des index communs. Ce guide complet explore diverses stratégies de jointure de DataFrames dans Pandas, vous dotant des connaissances nécessaires pour combiner et analyser efficacement les données provenant de différentes sources.
Comprendre la fusion et la jointure de DataFrames
La fusion et la jointure de DataFrames impliquent la combinaison de deux DataFrames ou plus en un seul DataFrame basé sur une colonne ou un index partagé. La principale différence entre `merge` et `join` est que `merge` est une fonction de la bibliothèque Pandas et joint généralement les DataFrames sur des colonnes, tandis que `join` est une méthode de DataFrame qui joint les DataFrames principalement sur des index, bien qu'elle puisse également être utilisée avec des colonnes.
Concepts clés
- DataFrames: Structures de données bidimensionnelles étiquetées avec des colonnes de types potentiellement différents.
- Colonnes/Index Communs: Colonnes ou index partageant le même nom et le même type de données à travers les DataFrames, servant de base pour la fusion/jointure.
- Types de Jointure: Différentes stratégies pour gérer les lignes non appariées pendant le processus de fusion/jointure, incluant les jointures internes, externes, gauches et droites.
Fusion de DataFrames avec `pd.merge()`
La fonction `pd.merge()` est l'outil principal pour fusionner les DataFrames basés sur les colonnes. Elle offre un moyen flexible de combiner des données basées sur une ou plusieurs colonnes communes.
Syntaxe
pd.merge(left, right, how='inner', on=None, left_on=None, right_on=None, left_index=False, right_index=False, sort=False, suffixes=('_x', '_y'), copy=True, indicator=False, validate=None)
Paramètres
- left: Le DataFrame de gauche Ă fusionner.
- right: Le DataFrame de droite Ă fusionner.
- how: Le type de fusion à effectuer ('inner', 'outer', 'left', 'right'). La valeur par défaut est 'inner'.
- on: Le nom de la ou des colonne(s) sur laquelle/lesquelles effectuer la jointure. Elles doivent se trouver dans les deux DataFrames.
- left_on: Le nom de la ou des colonne(s) dans le DataFrame de gauche à utiliser comme clé(s) de jointure.
- right_on: Le nom de la ou des colonne(s) dans le DataFrame de droite à utiliser comme clé(s) de jointure.
- left_index: Si True, utilise l'index du DataFrame de gauche comme clé(s) de jointure.
- right_index: Si True, utilise l'index du DataFrame de droite comme clé(s) de jointure.
- sort: Trie le DataFrame résultant lexicographiquement par les clés de jointure. La valeur par défaut est False.
- suffixes: Un tuple de suffixes de chaînes de caractères à appliquer aux noms de colonnes superposés. La valeur par défaut est ('_x', '_y').
- copy: Si False, évite de copier des données dans le nouveau DataFrame lorsque cela est possible. La valeur par défaut est True.
- indicator: Si True, ajoute une colonne nommée '_merge' indiquant la source de chaque ligne.
- validate: Vérifie si la fusion est du type spécifié. "one_to_one", "one_to_many", "many_to_one", "many_to_many".
Types de jointure expliqués
Le paramètre `how` dans `pd.merge()` détermine le type de jointure effectué. Les différents types de jointure gèrent les lignes non correspondantes de différentes manières.
Jointure interne (Inner Join)
Une jointure interne ne renvoie que les lignes qui ont des valeurs correspondantes dans les deux DataFrames basées sur les clés de jointure. Les lignes avec des valeurs non correspondantes sont exclues du résultat.
Exemple :
Considérons deux DataFrames :
import pandas as pd
# DataFrame 1: Customer Orders
df_orders = pd.DataFrame({
'order_id': [1, 2, 3, 4, 5],
'customer_id': [101, 102, 103, 104, 105],
'product_id': [1, 2, 1, 3, 2],
'quantity': [2, 1, 3, 1, 2]
})
# DataFrame 2: Customer Information
df_customers = pd.DataFrame({
'customer_id': [101, 102, 103, 106],
'customer_name': ['Alice', 'Bob', 'Charlie', 'David'],
'country': ['USA', 'Canada', 'UK', 'Australia']
})
# Inner Join
df_inner = pd.merge(df_orders, df_customers, on='customer_id', how='inner')
print(df_inner)
Sortie :
order_id customer_id product_id quantity customer_name country
0 1 101 1 2 Alice USA
1 2 102 2 1 Bob Canada
2 3 103 1 3 Charlie UK
Dans cet exemple, la jointure interne combine les DataFrames `df_orders` et `df_customers` sur la base de la colonne `customer_id`. Seuls les clients ayant passé des commandes sont inclus dans le résultat. Le client 'David' (customer_id 106) est exclu car il n'a aucune commande.
Jointure externe (Full Outer Join)
Une jointure externe renvoie toutes les lignes des deux DataFrames, y compris les lignes non correspondantes. Si une ligne n'a pas de correspondance dans l'autre DataFrame, les colonnes correspondantes contiendront des valeurs `NaN` (Not a Number).
Exemple :
# Outer Join
df_outer = pd.merge(df_orders, df_customers, on='customer_id', how='outer')
print(df_outer)
Sortie :
order_id customer_id product_id quantity customer_name country
0 1.0 101 1.0 2.0 Alice USA
1 2.0 102 2.0 1.0 Bob Canada
2 3.0 103 1.0 3.0 Charlie UK
3 4.0 104 3.0 1.0 NaN NaN
4 5.0 105 2.0 2.0 NaN NaN
5 NaN 106 NaN NaN David Australia
La jointure externe inclut tous les clients et toutes les commandes. Les clients 104 et 105 ont des commandes mais pas d'informations client, et le client 106 a des informations client mais pas de commandes. Les valeurs manquantes sont représentées par `NaN`.
Jointure gauche (Left Join)
Une jointure gauche renvoie toutes les lignes du DataFrame de gauche et les lignes correspondantes du DataFrame de droite. Si une ligne du DataFrame de gauche n'a pas de correspondance dans le DataFrame de droite, les colonnes correspondantes du DataFrame de droite contiendront des valeurs `NaN`.
Exemple :
# Left Join
df_left = pd.merge(df_orders, df_customers, on='customer_id', how='left')
print(df_left)
Sortie :
order_id customer_id product_id quantity customer_name country
0 1 101 1 2 Alice USA
1 2 102 2 1 Bob Canada
2 3 103 1 3 Charlie UK
3 4 104 3 1 NaN NaN
4 5 105 2 2 NaN NaN
La jointure gauche inclut toutes les commandes de `df_orders`. Les clients 104 et 105 ont des commandes mais pas d'informations client, donc les colonnes `customer_name` et `country` sont `NaN` pour ces commandes.
Jointure droite (Right Join)
Une jointure droite renvoie toutes les lignes du DataFrame de droite et les lignes correspondantes du DataFrame de gauche. Si une ligne du DataFrame de droite n'a pas de correspondance dans le DataFrame de gauche, les colonnes correspondantes du DataFrame de gauche contiendront des valeurs `NaN`.
Exemple :
# Right Join
df_right = pd.merge(df_orders, df_customers, on='customer_id', how='right')
print(df_right)
Sortie :
order_id customer_id product_id quantity customer_name country
0 1.0 101 1.0 2.0 Alice USA
1 2.0 102 2.0 1.0 Bob Canada
2 3.0 103 1.0 3.0 Charlie UK
3 NaN 106 NaN NaN David Australia
La jointure droite inclut tous les clients de `df_customers`. Le client 106 a des informations client mais pas de commandes, donc les colonnes `order_id`, `product_id` et `quantity` sont `NaN` pour ce client.
Jointure de DataFrames avec `df.join()`
La méthode `df.join()` est principalement utilisée pour joindre des DataFrames en fonction de leurs index. Elle peut également être utilisée pour joindre sur des colonnes, mais il est généralement plus pratique d'utiliser `pd.merge()` pour les jointures basées sur des colonnes.
Syntaxe
DataFrame.join(other, on=None, how='left', lsuffix='', rsuffix='', sort=False)
Paramètres
- other: L'autre DataFrame Ă joindre.
- on: Nom de la colonne sur laquelle joindre. Doit être passé si l'index n'est pas utilisé comme clé de jointure.
- how: Comment gérer l'opération des ensembles gauche et droit. La valeur par défaut est 'left'.
- lsuffix: Suffixe à utiliser pour le DataFrame de gauche pour remplacer les noms de colonnes superposés.
- rsuffix: Suffixe à utiliser pour le DataFrame de droite pour remplacer les noms de colonnes superposés.
- sort: Trie le DataFrame résultant lexicographiquement par les clés de jointure. La valeur par défaut est False.
Jointure sur l'index
Lors de la jointure sur l'index, le paramètre `on` n'est pas utilisé.
Exemple :
# DataFrame 1: Customer Orders with Customer ID as Index
df_orders_index = df_orders.set_index('customer_id')
# DataFrame 2: Customer Information with Customer ID as Index
df_customers_index = df_customers.set_index('customer_id')
# Join on Index (Left Join)
df_join_index = df_orders_index.join(df_customers_index, how='left')
print(df_join_index)
Sortie :
order_id product_id quantity customer_name country
customer_id
101 1 1 2 Alice USA
102 2 2 1 Bob Canada
103 3 1 3 Charlie UK
104 4 3 1 NaN NaN
105 5 2 2 NaN NaN
Dans cet exemple, la méthode `join()` est utilisée pour effectuer une jointure gauche sur l'index (`customer_id`). Le résultat est similaire à la jointure gauche utilisant `pd.merge()`, mais la jointure est basée sur l'index plutôt que sur une colonne.
Jointure sur colonne
Pour joindre sur une colonne en utilisant `df.join()`, vous devez spécifier le paramètre `on`.
Exemple :
# Joining on a column
df_join_column = df_orders.join(df_customers.set_index('customer_id'), on='customer_id', how='left')
print(df_join_column)
Sortie :
order_id customer_id product_id quantity customer_name country
0 1 101 1 2 Alice USA
1 2 102 2 1 Bob Canada
2 3 103 1 3 Charlie UK
3 4 104 3 1 NaN NaN
4 5 105 2 2 NaN NaN
Cet exemple montre comment joindre `df_orders` avec `df_customers` en utilisant la colonne `customer_id`. Notez que `customer_id` est défini comme index dans `df_customers` avant d'effectuer la jointure.
Gestion des colonnes superposées
Lors de la fusion ou de la jointure de DataFrames, il est courant de rencontrer des noms de colonnes superposés (colonnes ayant le même nom dans les deux DataFrames). Pandas fournit le paramètre `suffixes` dans `pd.merge()` et les paramètres `lsuffix` et `rsuffix` dans `df.join()` pour gérer ces situations.
Utilisation des `suffixes` dans `pd.merge()`
Le paramètre `suffixes` vous permet de spécifier des suffixes qui seront ajoutés aux noms de colonnes superposés pour les distinguer.
Exemple :
# DataFrame 1: Product Information
df_products1 = pd.DataFrame({
'product_id': [1, 2, 3],
'product_name': ['Product A', 'Product B', 'Product C'],
'price': [10, 20, 15]
})
# DataFrame 2: Product Information (with potentially updated prices)
df_products2 = pd.DataFrame({
'product_id': [1, 2, 4],
'product_name': ['Product A', 'Product B', 'Product D'],
'price': [12, 18, 25]
})
# Merge with suffixes
df_merged_suffixes = pd.merge(df_products1, df_products2, on='product_id', suffixes=('_old', '_new'))
print(df_merged_suffixes)
Sortie :
product_id product_name_old price_old product_name_new price_new
0 1 Product A 10 Product A 12
1 2 Product B 20 Product B 18
Dans cet exemple, les colonnes `product_name` et `price` sont présentes dans les deux DataFrames. Le paramètre `suffixes` ajoute les suffixes `_old` et `_new` pour distinguer respectivement les colonnes des DataFrames gauche et droit.
Utilisation de `lsuffix` et `rsuffix` dans `df.join()`
Les paramètres `lsuffix` et `rsuffix` offrent des fonctionnalités similaires pour `df.join()`. `lsuffix` est ajouté aux colonnes superposées du DataFrame de gauche, et `rsuffix` à celles du DataFrame de droite.
Exemple :
# Join with lsuffix and rsuffix
df_products1_index = df_products1.set_index('product_id')
df_products2_index = df_products2.set_index('product_id')
df_joined_suffixes = df_products1_index.join(df_products2_index, lsuffix='_old', rsuffix='_new', how='outer')
print(df_joined_suffixes)
Sortie :
product_name_old price_old product_name_new price_new
product_id
1 Product A 10.0 Product A 12.0
2 Product B 20.0 Product B 18.0
3 Product C 15.0 NaN NaN
4 NaN NaN Product D 25.0
Exemples pratiques et cas d'utilisation
La fusion et la jointure de DataFrames sont largement utilisées dans divers scénarios d'analyse de données. Voici quelques exemples pratiques :
Combinaison des données de vente avec les informations produit
Un cas d'utilisation courant est de combiner les données de vente avec les informations produit. Supposons que vous ayez un DataFrame contenant les transactions de vente et un autre DataFrame contenant les détails des produits. Vous pouvez fusionner ces DataFrames pour enrichir les données de vente avec les informations produit.
Exemple :
# Sales Transactions Data
df_sales = pd.DataFrame({
'transaction_id': [1, 2, 3, 4, 5],
'product_id': [101, 102, 103, 101, 104],
'quantity': [2, 1, 3, 1, 2],
'sales_date': ['2023-01-15', '2023-02-20', '2023-03-10', '2023-04-05', '2023-05-01']
})
# Product Information Data
df_products = pd.DataFrame({
'product_id': [101, 102, 103, 104],
'product_name': ['Laptop', 'Mouse', 'Keyboard', 'Monitor'],
'category': ['Electronics', 'Electronics', 'Electronics', 'Electronics'],
'price': [1200, 25, 75, 300]
})
# Merge Sales Data with Product Information
df_sales_enriched = pd.merge(df_sales, df_products, on='product_id', how='left')
print(df_sales_enriched)
Sortie :
transaction_id product_id quantity sales_date product_name category price
0 1 101 2 2023-01-15 Laptop Electronics 1200
1 2 102 1 2023-02-20 Mouse Electronics 25
2 3 103 3 2023-03-10 Keyboard Electronics 75
3 4 101 1 2023-04-05 Laptop Electronics 1200
4 5 104 2 2023-05-01 Monitor Electronics 300
Le DataFrame résultant `df_sales_enriched` contient les transactions de vente ainsi que les informations produit correspondantes, permettant une analyse plus détaillée des tendances de vente et de la performance des produits.
Combinaison des données client avec les informations démographiques
Un autre cas d'utilisation courant est de combiner les données client avec les informations démographiques. Cela permet d'analyser le comportement des clients en fonction de facteurs démographiques.
Exemple :
# Customer Data
df_customers = pd.DataFrame({
'customer_id': [1, 2, 3, 4, 5],
'customer_name': ['Alice', 'Bob', 'Charlie', 'David', 'Eve'],
'city': ['New York', 'London', 'Tokyo', 'Sydney', 'Berlin']
})
# Demographic Information Data
df_demographics = pd.DataFrame({
'city': ['New York', 'London', 'Tokyo', 'Sydney', 'Berlin'],
'population': [8419000, 8982000, 13960000, 5312000, 3769000],
'average_income': [75000, 65000, 85000, 90000, 55000]
})
# Merge Customer Data with Demographic Information
df_customer_demographics = pd.merge(df_customers, df_demographics, on='city', how='left')
print(df_customer_demographics)
Sortie :
customer_id customer_name city population average_income
0 1 Alice New York 8419000 75000
1 2 Bob London 8982000 65000
2 3 Charlie Tokyo 13960000 85000
3 4 David Sydney 5312000 90000
4 5 Eve Berlin 3769000 55000
Le DataFrame résultant `df_customer_demographics` contient les données client ainsi que les informations démographiques pour leurs villes respectives, permettant l'analyse du comportement client basée sur la démographie des villes.
Analyse des données de la chaîne d'approvisionnement mondiale
La fusion Pandas est précieuse pour l'analyse des données de la chaîne d'approvisionnement mondiale, où les informations sont souvent réparties sur plusieurs tables. Par exemple, lier les données des fournisseurs, les informations d'expédition et les chiffres de vente peut révéler des goulots d'étranglement et optimiser la logistique.
Exemple :
# Supplier Data
df_suppliers = pd.DataFrame({
'supplier_id': [1, 2, 3],
'supplier_name': ['GlobalTech', 'EuroParts', 'AsiaSource'],
'location': ['Taiwan', 'Germany', 'China']
})
# Shipping Data
df_shipments = pd.DataFrame({
'shipment_id': [101, 102, 103, 104],
'supplier_id': [1, 2, 3, 1],
'destination': ['USA', 'Canada', 'Australia', 'Japan'],
'shipment_date': ['2023-01-10', '2023-02-15', '2023-03-20', '2023-04-25']
})
# Merge Supplier and Shipment Data
df_supply_chain = pd.merge(df_shipments, df_suppliers, on='supplier_id', how='left')
print(df_supply_chain)
Sortie :
shipment_id supplier_id destination shipment_date supplier_name location
0 101 1 USA 2023-01-10 GlobalTech Taiwan
1 102 2 Canada 2023-02-15 EuroParts Germany
2 103 3 Australia 2023-03-20 AsiaSource China
3 104 1 Japan 2023-04-25 GlobalTech Taiwan
Techniques de fusion avancées
Fusion sur plusieurs colonnes
Vous pouvez fusionner des DataFrames basés sur plusieurs colonnes en passant une liste de noms de colonnes au paramètre `on`.
Exemple :
# DataFrame 1
df1 = pd.DataFrame({
'product_id': [1, 1, 2, 2],
'color': ['red', 'blue', 'red', 'blue'],
'quantity': [10, 15, 20, 25]
})
# DataFrame 2
df2 = pd.DataFrame({
'product_id': [1, 1, 2, 2],
'color': ['red', 'blue', 'red', 'blue'],
'price': [5, 7, 8, 10]
})
# Merge on multiple columns
df_merged_multiple = pd.merge(df1, df2, on=['product_id', 'color'], how='inner')
print(df_merged_multiple)
Sortie :
product_id color quantity price
0 1 red 10 5
1 1 blue 15 7
2 2 red 20 8
3 2 blue 25 10
Fusion avec des noms de colonnes différents
Si les colonnes de jointure ont des noms différents dans les deux DataFrames, vous pouvez utiliser les paramètres `left_on` et `right_on` pour spécifier les noms de colonnes à utiliser pour la fusion.
Exemple :
# DataFrame 1
df1 = pd.DataFrame({
'product_id': [1, 2, 3],
'product_name': ['Product A', 'Product B', 'Product C']
})
# DataFrame 2
df2 = pd.DataFrame({
'id': [1, 2, 4],
'price': [10, 20, 25]
})
# Merge with different column names
df_merged_different = pd.merge(df1, df2, left_on='product_id', right_on='id', how='left')
print(df_merged_different)
Sortie :
product_id product_name id price
0 1 Product A 1.0 10.0
1 2 Product B 2.0 20.0
2 3 Product C NaN NaN
Utilisation de `indicator` pour l'analyse de fusion
Le paramètre `indicator` dans `pd.merge()` ajoute une colonne nommée `_merge` au DataFrame résultant, indiquant la source de chaque ligne. Ceci est utile pour comprendre quelles lignes ont été correspondantes et lesquelles ne l'ont pas été.
Exemple :
# Merge with indicator
df_merged_indicator = pd.merge(df_orders, df_customers, on='customer_id', how='outer', indicator=True)
print(df_merged_indicator)
Sortie :
order_id customer_id product_id quantity customer_name country _merge
0 1.0 101 1.0 2.0 Alice USA both
1 2.0 102 2.0 1.0 Bob Canada both
2 3.0 103 1.0 3.0 Charlie UK both
3 4.0 104 3.0 1.0 NaN NaN left_only
4 5.0 105 2.0 2.0 NaN NaN left_only
5 NaN 106 NaN NaN David Australia right_only
La colonne `_merge` indique si la ligne provient des deux DataFrames (`both`), uniquement du DataFrame de gauche (`left_only`), ou uniquement du DataFrame de droite (`right_only`).
Validation des types de fusion
Le paramètre `validate` garantit que l'opération de fusion s'aligne avec les types de relations attendus entre les DataFrames (par exemple, 'one_to_one', 'one_to_many'). Cela aide à prévenir les incohérences et les erreurs de données.
Exemple :
# Example with one-to-one validation
df_users = pd.DataFrame({
'user_id': [1, 2, 3],
'username': ['john_doe', 'jane_smith', 'peter_jones']
})
df_profiles = pd.DataFrame({
'user_id': [1, 2, 3],
'profile_description': ['Software Engineer', 'Data Scientist', 'Project Manager']
})
# Performing a one-to-one merge with validation
merged_df = pd.merge(df_users, df_profiles, on='user_id', validate='one_to_one')
print(merged_df)
Si la fusion viole la validation spécifiée (par exemple, une relation de plusieurs à un lorsqu'une relation 'one_to_one' est spécifiée), une `MergeError` sera levée, vous alertant de problèmes potentiels d'intégrité des données.
Considérations de performance
La fusion et la jointure de DataFrames peuvent être coûteuses en calcul, en particulier pour les grands ensembles de données. Voici quelques conseils pour améliorer les performances :
- Utilisez le type de jointure approprié : Choisir le bon type de jointure peut avoir un impact significatif sur les performances. Par exemple, si vous n'avez besoin que des lignes correspondantes, utilisez une jointure interne.
- Indexez les colonnes de jointure : L'indexation des colonnes de jointure peut accélérer le processus de fusion.
- Utilisez des types de données appropriés : Assurez-vous que les colonnes de jointure ont des types de données compatibles.
- Évitez les copies inutiles : Définissez `copy=False` dans `pd.merge()` et `df.join()` pour éviter de créer des copies inutiles des données.
Conclusion
La fusion et la jointure de DataFrames sont des opérations fondamentales en analyse de données. En comprenant les différents types et techniques de jointure, vous pouvez combiner et analyser efficacement les données provenant de diverses sources, débloquant ainsi des informations précieuses et favorisant une prise de décision éclairée. Qu'il s'agisse de combiner des données de vente avec des informations sur les produits ou d'analyser des chaînes d'approvisionnement mondiales, la maîtrise de ces techniques vous permettra d'aborder les tâches complexes de manipulation de données avec confiance. N'oubliez pas de prendre en compte les implications en matière de performances lorsque vous travaillez avec de grands ensembles de données et de tirer parti des fonctionnalités avancées comme les paramètres `indicator` et `validate` pour une analyse plus robuste et pertinente.